﻿$(document).ready(function () {
    if (typeof (VOFFICE) == "undefined") {
        // ReSharper disable AssignToImplicitGlobalInFunctionScope
        VOFFICE = {};
        // ReSharper restore AssignToImplicitGlobalInFunctionScope
    }

    VOFFICE.CreateFlow = (function () {
        var methods = {};
        var $step1FlowForm = $('#step1-flow-form');
        var $step2NodeForm = $('#step2-node-form');
        var $flowActionMain = $('#flow-action-main');
        var $step2NodeLlist = $('#step2-node-list');
        var $fullDetails = $('#full-details');
        var $flowAction = $('#flow-action');
        var $needStart = $('#node-need-start');

        var $dialog = $('#dialog').dialog({
            autoOpen: false,
            show: "fade",
            hide: "fade",
            modal: true,
            height: 'auto',
            width: 600,
            open: function (event, ui) {
            },
            close: function (event, ui) {
            }
        });

        methods.Prefix = "n-";
        methods.DocTypeList = null;
        methods.RoleList = null;
        methods.Params = null;

        methods.FlowForm = null;
        methods.FlowFormValidate = {
            errorLabelContainer: "#flow-form-error",
            rules: {
                Name: { required: true },
                Description: { required: true }
            },
            messages: {
                Name: { required: jsResources.lang.CreateFlowFlowFormNameRequired },
                Description: { required: jsResources.lang.CreateFlowFlowFormDescriptionRequired }
            }
        };
        methods.NodeForm = null;
        methods.NodeFormValidate = {
            errorLabelContainer: "#node-form-error",
            rules: {
                Node_Name: { required: true }
            },
            messages: {
                Node_Name: { required: jsResources.lang.CreateFlowNodeFormNameRequired }
            }
        };
        methods.TodoForm = null;
        methods.TodoFormValidate = {
            errorLabelContainer: '#todo-form-error',
            rules: {
                Todo_Name: { required: true }
            },
            messages: {
                Todo_Name: { required: jsResources.lang.CreateFlowNodeFormNameRequired }
            }
        };

        methods.NodeCollection = null;
        methods.NodeGrid = null;
        methods.NodeRelationGrid = null;

        methods.NeedStartNode = true;

        methods.hintStartingNode = function () {
            ///<summary>
            /// Hiển thị hay ẩn thông báo cần nút start
            ///</summary>
            if (methods.NodeCollection && methods.NodeCollection.length > 0) {
                //console.log(methods.NodeCollection);
                for (var i = 0; i < methods.NodeCollection.length; i++) {
                    if (methods.NodeCollection.models[i].get('IsStart') == true) {
                        $needStart.fadeOut();
                        return;
                    }
                }
            }
            $needStart.fadeIn("fast");
        };

        methods.onlyOneStartingNode = function (newStartingNode) {
            ///<summary>
            /// Chỉ cho phép một node là node bắt đầu trong luồng
            ///</summary>
            if (methods.NodeCollection && methods.NodeCollection.length > 0) {
                //console.log(methods.NodeCollection);
                for (var i = 0; i < methods.NodeCollection.length; i++) {
                    var model = methods.NodeCollection.models[i];
                    if (model.get('IsStart') == true && model.id != newStartingNode.id) {
                        //                        alert('123');
                        model.set({ 'IsStart': false });
                        model.trigger('change');
                        return;
                    }
                }
            }
        };
        /*
        Lấy toàn bộ thông tin của node sinh html bằng backbone và gọi thư viện jsPlumb sau khi đã có html 
        Hàm được gọi sau khi chắc chắn flow đã tồn tại, hoặc node đã được sinh ra
        */
        methods.loadNode = function (flowid) {
            ///<summary>
            /// Tải toàn bộ nút của luồng từ database, đưa nút vào Collection và gọi NodeGrid để hiển thị NodeRelationGrid để tạo liên kết
            ///</summary>
            if (!methods.NodeCollection) {
                methods.NodeCollection = new NodeCollection();
                methods.NodeRelationGrid = new NodeRelationGrid({ collection: methods.NodeCollection });
                methods.NodeGrid = new NodeGrid({ collection: methods.NodeCollection });
                $flowActionMain.html(methods.NodeRelationGrid.render().el);
                $step2NodeLlist.html(methods.NodeGrid.render().el);
            }
            if (!flowid) {
                return;
            };
            SaveIndicator.indicate($.get('/node/get_by_flow_id', { flowId: flowid, nocache: (new Date()).toJSON() }, function (data) {
                if (!!data && data.Status == true) {
                    if (!!data.Result && data.Result.length > 0) {
                        _.each(data.Result, function (item) {
                            if (methods.NeedStartNode) {
                                methods.NeedStartNode = !item.IsStart;
                            }
                            var node = new Node({
                                'id': item.Id,
                                'Name': item.Name,
                                'Description': item.Description,
                                'FlowId': item.FlowId,
                                'RoleId': item.RoleId,
                                'RoleName': item.RoleName,
                                'IsDocNode': item.IsDocNode,
                                'IsStart': item.IsStart,
                                'CreatedAt': item.CreatedAt,
                                'UpdatedAt': item.UpdatedAt,
                                'NextNodeList': item.NextNodeList,
                                'NextNodeJson': item.NextNodeJson,
                                'UserInNode': item.UserInNode,
                                'TodoInNode': item.TodoInNode
                            });
                            methods.NodeCollection.push(node);
                        });

                        //gọi hàm khởi tạo jsPlumb
                        methods.jsPlumbNode.init();
                        //gọi hàm kết nối các  node
                        methods.initRelation();

                        methods.showNodeForm(new Node({ 'IsStart': VOFFICE.CreateFlow.NeedStartNode })); //Node_IsStart
                        methods.hintStartingNode();
                    }
                }
            }));
        };

        /* 
        Lưu kết quả của việc kéo thả vào csdl
        */
        methods.saveRelation = function (fromId, toId) {
            ///<summary>
            /// Lưu thông tin quan hệ của 2 nút vào csdl (sau khi kéo thả)
            ///</summary>
            SaveIndicator.indicate($.post('/NodeRelation/add_node_relation', {
                FlowId: methods.FlowForm.model.get('id'),
                ToNodeId: toId,
                FromNodeId: fromId,
                nocache: (new Date()).toJSON()
            }, function (data) {
                if (!data || data.Status == false) {
                }
            }));
        };

        /* xóa bỏ một quan hệ */
        methods.removeRelation = function (fromId, toId) {
            ///<summary>
            /// Lưu hủy quan hệ giữa 2 nút vào csdl, sau khi hủy trên giao diện
            ///</summary>
            SaveIndicator.indicate($.post('/NodeRelation/remove_node_relation', {
                ToNodeId: toId,
                FromNodeId: fromId,
                nocache: (new Date()).toJSON()
            }, function (data) {
                if (!data || data.Status == false) {
                    VH.MessageBox(jsResources.lang.RequestError, function () {
                        location.reload();
                    });
                }
            }));
        };

        methods.BlockSaving = false;
        /* KHỞI TẠO JSPLUMB ĐỂ TẠO LUỒNG */
        /* 
        Khởi tạo thư viện kéo thả để tạo quan hệ giữa các node trong luồng 
        chú ý răng, việc khởi tạo lại không ảnh hưởng đến các node đã tạo
        nhưng việc sinh quan hệ ban đầu không thực hiện ở đây mà phải làm ở nơi khác
        về cơ bản các bước sẽ như sau
        1. Dung backbone để sinh ra html
        2. Gọi hàm khởi tạo này
        3. Từ thông tin về từng node(chứa trong thẻ div) thì bắt đầu tạo quan hệ
        */
        methods.jsPlumbNode = {
            ///<summary>
            /// Khởi tạo thư viện tạo quan hệ luồng giữa các nút
            ///</summary>
            init: function () {

                // setup some defaults for jsPlumb.	
                jsPlumb.importDefaults({
                    Endpoint: ["Dot", { radius: 2}],
                    HoverPaintStyle: { strokeStyle: "#42a62c", lineWidth: 2 },
                    ConnectionOverlays: [
                            ["Arrow", {
                                location: 1,
                                id: "arrow",
                                length: 14,
                                foldback: 0.8
                            }],
                            ["Label", { label: " ", id: "label"}]
                        ]
                });

                // sưa sự kiện kéo thả vào từng node
                jsPlumb.draggable($(".w"));

                // Sư kiện xẩy ra khi một quan hệ giữa các node bị hủy
                jsPlumb.bind("click", function (c) {
                    // gọi hàm xóa trong db
                    methods.removeRelation(c.sourceId.replace(methods.Prefix, ""), c.targetId.replace(methods.Prefix, ""));
                    jsPlumb.detach(c);
                });

                // biến các node có div với class ="ep" có khả năng tạo ra các quan hệ
                $(".ep").each(function (i, e) {
                    var p = $(e).parent();
                    jsPlumb.makeSource($(e), {
                        parent: p,
                        anchor: "Continuous",
                        connector: ["StateMachine", { curviness: 20}],
                        connectorStyle: { strokeStyle: nextColour(), lineWidth: 2 },
                        maxConnections: 5,
                        onMaxConnections: function (info, e) {
                            alert("Maximum connections (" + info.maxConnections + ") reached");
                        }
                    });
                });

                // sự kiện xẩy ra sau  khi một quan hệ giữa các nút được thiết lập
                jsPlumb.bind("connection", function (info) {
                    //Lấy thông tin từ info và lưu vào csdl ở đây
                    if (methods.BlockSaving) {
                        methods.saveRelation(info.sourceId.replace(methods.Prefix, ""), info.targetId.replace(methods.Prefix, ""));
                    }
                    info.connection.setPaintStyle({ strokeStyle: nextColour() });
                });

                // initialise all '.w' elements as connection targets.
                jsPlumb.makeTarget($(".w"), {
                    dropOptions: { hoverClass: "dragHover" },
                    anchor: "Continuous"
                });
            }
        };
        /* 
        Khởi tạo quan hệ giữa các node 
        */
        methods.initRelation = function () {
            ///<summary>
            /// Khỏi tạo quan hệ giữa các nút với thông tin từ các attribute của các nút (html)
            ///</summary>
            methods.BlockSaving = false;
            var divNodes = $flowActionMain.find('.w');
            if (divNodes.length > 0) {
                _.each(divNodes, function (node) {
                    var strNextNodes = $(node).attr('relation');
                    if (!!strNextNodes) {
                        var nextNodes = JSON.parse(strNextNodes);
                        if (!!nextNodes && nextNodes.length > 0) {
                            _.each(nextNodes, function (id) {
                                jsPlumb.connect({
                                    source: $(node).attr('id'),
                                    target: methods.Prefix + id
                                });
                            });
                        }
                    }
                });
            }
            methods.BlockSaving = true;
        };

        /* 
        Lấy giá trị key-value
        */
        var getKeyValue = function () {
            /// <summary>
            /// Lấy các giá trị dạng keyvalue dùng để đưa vào các form nhập
            ///</summary>
            var load = 2;
            if (!methods.DocTypeList) {
                SaveIndicator.indicate($.get('/keyvalue/get_doctype_list', { nocache: (new Date()).toJSON() }, function (data) {
                    if (!!data && data.Status == true) {
                        methods.DocTypeList = data.Result;
                        //gọi hàm tải flow sau khi các thông tin đã sẵn sàng
                        load--;
                        if (load == 0)
                            loadFlow();
                    }
                }));
            }

            if (!methods.RoleList) {
                SaveIndicator.indicate($.get('/keyvalue/get_role_list', { nocache: (new Date()).toJSON() }, function (data) {
                    if (!!data && data.Status == true) {
                        methods.RoleList = data.Result;
                        methods.showNodeForm(new Node({ 'IsStart': VOFFICE.CreateFlow.NeedStartNode })); //Node_IsStart
                    }
                }));
            }

            if (!methods.DepartmentList) {
                SaveIndicator.indicate($.get('/keyvalue/get_department_tree', { nocache: (new Date()).toJSON() }, function (data) {
                    if (!!data && data.Status == true) {
                        methods.DepartmentList = data.Result;
                        load--;
                        if (load == 0)
                            loadFlow();
                    }
                }));
            }
        };
        /* 
        Lấy ra luồng hiện tại
        */
        var loadFlow = function () {
            ///<summary>
            /// Lấy thông tin của luồng (khi có request luồng bằng id trên url 
            ///</summary>
            if (!methods.Params) {
                methods.Params = $.url(document.URL.toLowerCase()).param();
                if (!!methods.Params && !!methods.Params.id) {
                    SaveIndicator.indicate($.get('/flow/get_one', { id: methods.Params.id }, function (data) {
                        if (!!data && data.Status == true) {
                            var flow = new Flow({
                                'id': data.Result.Id,
                                'Name': data.Result.Name,
                                'Description': data.Result.Description,
                                'DocTypeId': data.Result.DocTypeId,
                                'IsActive': data.Result.IsActive,
                                'IsCommon': data.Result.IsCommon,
                                'IsDefault': data.Result.IsDefault,
                                'DepartmentId': data.Result.DepartmentId
                            });
                            //gọi hàm lấy ra tốt cả các node trong luồng
                            methods.loadNode(data.Result.Id);
                            showFlowForm(flow);
                            methods.ShowFullPage();
                        }
                    }));
                } else {
                    methods.loadNode();
                    showFlowForm(new Flow());
                }
            }
        };

        methods.ShowFullPage = function () {
            /// <summary>
            /// Hiển thị đầy đủ 3 bước của trang
            /// </summary>  
            $flowAction.fadeIn();
            $fullDetails.fadeIn();
        };

        /* 
        Hiển thị form tạo mới 
        */
        var showFlowForm = function (model) {
            ///<summary>
            /// Hiển thị form nhập, sửa thông tin của luồng.
            ///</summary>
            methods.FlowForm = new FlowForm({ model: model });
            $step1FlowForm.html(methods.FlowForm.render().el);
            $('#flow-form').validate(methods.FlowFormValidate);
            $('#flow-form input[type=submit]').button().addClass('ui-button-primary');
        };

        /* 
        Hiển thị sửa node 
        */
        methods.showNodeForm = function (node) {
            ///<summary>
            /// Hiện thị form nhập, sửa thông tin của nút 
            ///</summary>
            methods.NodeForm = new NodeForm({ model: node });
            $step2NodeForm.html(methods.NodeForm.render().el);
            $('#node-form').validate(methods.NodeFormValidate);
            $('#node-form input[type=submit]').button();
        };

        /* 
        Hiển thị form thêm công việc cho node 
        */
        methods.showTodoForm = function (model, node) {
            ///<summary>
            /// Hiển thị form nhập, sửa thông tin của _TODO
            ///</summary>
            $dialog.html('');
            methods.TodoForm = new TodoForm({
                model: model,
                node: node
            });
            $dialog.dialog({ title: jsResources.lang.CreatFlowTodoFormTitle });
            $dialog.bind('dialogclose', function () {
                methods.TodoForm.close();
            });
            $dialog.html(methods.TodoForm.render().el);
            $('#todo-form').validate(methods.TodoFormValidate);
            $('#todo-form input[type=submit]').button();
            $dialog.dialog('open');
            methods.TodoForm.initUpload();
        };

        /* 
        Gọi lại hàm validate dữ liệu 
        */
        methods.reCallFFValidate = function () {
            ///<summary>
            /// Gọi lại hàm validate form nhập thông tin cơ bản của luồng
            ///</summary>
            $('#flow-form').validate(methods.FlowFormValidate);
            $('#flow-form input[type=submit]').button().addClass('ui-button-primary');
        };
        methods.reCallNFValidate = function () {
            ///<summary>
            /// Gọi lại hàm validate form nhập nút
            ///</summary>
            $('#node-form').validate(methods.NodeFormValidate);
            $('#node-form input[type=submit]').button();
        };
        methods.reCallTFValidate = function () {
            $('todo-form').validate(methods.TodoFormValidate);
            $('#todo-form input[type=submit]').button();
        };

        // quy ước về hàm khởi tạo
        methods.init = function () {
            ///<summary>
            /// Khởi tạo dữ liệu ban đầu
            ///</summary>
            /* hàm lấy dữ liệu được nhúng vào đây */
            getKeyValue();
        };
        return methods;
    })(VOFFICE.CreateFlow);

    //gọi hàm khởi tạo
    VOFFICE.CreateFlow.init();
});

/* 
View tạo mới một công việc cho node
*/
window.TodoForm = Backbone.View.extend({
    node: null,
    events: {
        'click .choose-from-library': 'showLibrary'
    },

    showLibrary: function (event) {
        ///<summary>
        /// Hiển thị list các mẫu công văn, phiếu trình có trong library để thêm vào _TODO
        ///</summary>
        var self = this;
        VH.ShowLibrary(function () {
            if (!!window.SelectedLibItemId) {
                self.model.set({ 'LibraryId': window.SelectedLibItemId, 'LibraryItemName': window.SelectedLibItemName }, { silent: true });
                //self.initUpload();
                $('.span-library-item-name').text(window.SelectedLibItemName);
            }
        });
    },

    initialize: function (options) {
        ///<summary>
        /// Khởi tạo cho TODOFORM 
        ///</summary>
        this.node = options.node;
        $('#todo-form').die("submit", this.submitTodo);
        $('#todo-form').live("submit", this.submitTodo);
        this.model.bind("change", this.render, this);
        this.model.bind("destroy", this.close, this);
    },

    submitTodo: function (event) {
        ///<summary>
        /// Lưu _TODO vào csdl
        ///</summary>
        var self = VOFFICE.CreateFlow.TodoForm;
        if (!self) return;
        SaveIndicator.indicate(self.model.save({
            'Name': $('#Todo_Name').val(),
            'Description': $('#Todo_Description').val(),
            'IsActive': $('#Todo_IsActive').is(':checked'),
            'IsCheckList': $('#Todo_IsCheckList').is(':checked') == false
        }, {
            success: function (data) {
                if (!!data && data.get('Status') == true) {
                    // Cập nhập vào _todo chứa node này
                    if (!!self.node) {
                        var newKeyValueTodo = {
                            Key: self.model.get('id'),
                            Value: self.model.get('Name'),
                            Selected: self.model.get('IsCheckList')
                        };
                        var list = self.node.get('TodoInNode');
                        list.push(newKeyValueTodo);
                        self.node.set({ 'TodoInNode': list });
                        self.node.trigger('change');
                        var thisNode = self.node;
                        // Tạo lại form nhập
                        var newTodo = new Todo({ 'NodeId': self.model.get('NodeId') });
                        VOFFICE.CreateFlow.TodoForm.close();
                        VOFFICE.CreateFlow.showTodoForm(newTodo, thisNode);
                    }
                } else {
                    VH.MessageBox(jsResources.lang.RequestErrorAndRefresh, function () {
                        location.reload();
                    });
                }
            },
            complete: function () {
            }
        }));
    },

    initUpload: function () {
        ///<summary>
        /// Khởi tạo upload cho form nhập _todo
        ///</summary>
        var self = this;
        this.TodoUploader = new qq.FileUploader({
            uploadButtonText: jsResources.lang.QQ_uploadButtonText,
            cancelButtonText: jsResources.lang.QQ_cancelButtonText,
            failUploadText: jsResources.lang.QQ_failUploadText,
            // pass the dom node (ex. $(selector)[0] for jQuery users)
            element: document.getElementById('todo-upload-button'),
            // path to server-side upload script
            action: '/file/upload',
            multiple: false,
            params: { 'folder': '/Assets/library/' },
            onSubmit: function (id, fileName) {
            },
            onComplete: function (id, fileName, responseJson) {
                if (!!responseJson && responseJson.success == true) {
                    self.model.set({ 'DocTemplate': responseJson.path }, { silent: true });
                }
            }
        });
    },

    render: function (node) {
        ///<summary>
        /// View _TODO render html và trả về el
        ///</summary>
        this.template = _.template($('#todo-form-template').html());
        $(this.el).html(this.template({ model: this.model.toJSON() }));
        return this;
    },

    close: function () {
        ///<summary>
        /// Hủy TodoFrom
        ///</summary>

        this.unbind();
        this.model.unbind("change", this.render, this);
        this.remove();
    }
});

/* 
View để thêm và chỉnh sửa từng nút trong luồng
*/
window.NodeForm = Backbone.View.extend({
    events: {
    },

    initialize: function () {
        ///<summary>
        /// Khởi tạo cho NODEFORM 
        ///</summary>
        $('#node-form').die("submit", this.submitNode);
        $('#node-form').live("submit", this.submitNode);
        this.model.bind("change", this.render, this);
        this.model.bind("destroy", this.close, this);
    },

    /* thêm hoặc lưu một node */
    submitNode: function (event) {
        ///<summary>
        /// Lưu thông tin của NODE vào csdl
        ///</summary>        
        event.preventDefault();
        var self = VOFFICE.CreateFlow.NodeForm;
        if (!self) return;
        var isNew = self.model.isNew();
        SaveIndicator.indicate(self.model.save({
            'Name': $('#Node_Name').val(),
            'Description': $('#Node_Description').val(),
            'RoleId': $('#Node_RoleId').val(),
            'IsStart': $('#Node_IsStart').is(':checked'),
            'IsDocNode': $('#Node_IsDocNode').is(':checked'),
            'FlowId': VOFFICE.CreateFlow.FlowForm.model.get('id'),
            'RoleName': $('#Node_RoleId option:selected').text()
        }, { success: function (data) {
            if (!!data && data.get('Status') == true) {
                var newModel = data;
                //đóng node cũ
                self.close();
                VOFFICE.CreateFlow.NodeCollection.push(newModel);
                VOFFICE.CreateFlow.jsPlumbNode.init();
                //và hiển thị form nhập node mới
                VOFFICE.CreateFlow.showNodeForm(new Node({ 'IsStart': VOFFICE.CreateFlow.NeedStartNode && !newModel.get('IsStart') }));
                if (newModel.get('IsStart')) {
                    VOFFICE.CreateFlow.onlyOneStartingNode(newModel);
                }
                VOFFICE.CreateFlow.hintStartingNode();
                if (isNew) {
                    $(document).scrollTop($(document).height());
                }
            } else {
                VH.MessageBox(jsResources.lang.RequestErrorAndRefresh, function () {
                    location.reload();
                });
            }
        }
        }));
    },

    render: function () {
        ///<summary>
        /// Sinh html và el của NODEFORM
        ///</summary>           
        this.template = _.template($('#node-form-template').html());
        $(this.el).html(this.template({ model: this.model.toJSON() }));
        return this;
    },

    close: function () {
        ///<summary>
        /// Hủy NODEFORM
        ///</summary>           
        this.unbind();
        this.model.unbind("change", this.render, this);
        this.remove();
    }
});

/*
View để thêm mới hay chỉnh sửa luồng
*/
window.FlowForm = Backbone.View.extend({
    events: {
        'change #DocTypeId': 'changeUsable',
        'change #IsCommon': 'changeUsable'
    },

    /* chuyển đổi giữa sử dụng chung và sử dụng riêng cho 1 loại công văn cụ thể nào đó */
    changeUsable: function (event) {
        var $target = $(event.currentTarget);
        if ($target.prop('tagName') == "INPUT") {
            if ($target.is(':checked')) {
                $('#DocTypeId').val(0);
            }
        } else {
            if (parseFloat($target.val()) != 0) {
                $('#IsCommon').removeAttr('checked');
            } else {
                $('#IsCommon').attr({ 'checked': 'checked' });
            }
        }
    },

    initialize: function () {
        //đưa sự kiện vào đây nếu đưa ở events thì ko validate được dữ  liệu
        //đang tìm nguyên nhân
        $('#flow-form').die('submit', this.submitFlow);
        $('#flow-form').live('submit', this.submitFlow);
        //bind để tự động cập nhập lại dữ liệu khi các field của model thay đổi
        this.model.bind("change", this.render, this);
        this.model.bind("destroy", this.close, this);
    },

    /* 
    Cập nhập hoặc thêm mới sổ văn bản 
    */
    submitFlow: function (event) {
        event.preventDefault();
        var self = VOFFICE.CreateFlow.FlowForm;
        if (!self) return;
        var isNew = self.model.isNew();
        //tao moi hay cap nhap du lieu
        SaveIndicator.indicate(self.model.save({
            'Name': $('#Name').val(),
            'Description': $('#Description').val(),
            'DocTypeId': $('#DocTypeId').val(),
            'IsCommon': $('#IsCommon').is(':checked'),
            'IsActive': $('#IsActive').is(':checked'),
            'IsDefault' : $('#IsDefault').is(':checked'),
            'DepartmentId': $('#DepartmentId').val()
        }, {
            success: function (data) {
                if (!!data && data.get('Status') == true) {
                    if (isNew) {
                        var flowId = self.model.get('id');
                        History.pushState({ state: flowId }, document.title, '?id=' + flowId);
                        VOFFICE.CreateFlow.loadNode(flowId);
                        VOFFICE.CreateFlow.ShowFullPage();
                    } else {

                    }
                } else {
                    VH.MessageBox(jsResources.lang.RequestErrorAndRefresh, function () {
                        location.reload();
                    });
                }
            },
            error: function (data) {

            },
            complete: function () {
                VOFFICE.CreateFlow.reCallFFValidate();
                return false;
            }
        }));
    },

    render: function () {
        this.template = _.template($('#flow-form-template').html());
        $(this.el).html(this.template({ model: this.model.toJSON() }));
        return this;
    },

    close: function () {

        this.unbind();
        this.model.unbind("change", this.render, this);
        this.remove();
    }
});
/* 
List node đã tạo 
*/
window.NodeGrid = Backbone.View.extend({
    tagName: 'div',
    render: function () {
        $(this.el).html('');
        _.each(this.collection.models, function (node) {
            $(this.el).append((new NodeGridItem({ model: node })).render().el);
        }, this);
        return this;
    },

    /* 
    Khi grid có thêm bản ghi thì cập nhập
    */
    initialize: function () {
        var self = this;
        this.collection.bind("reset", this.render, this);
        self.collection.bind("add", function (node) {
            $(self.el).append(new NodeGridItem({ model: node }).render().el);
        });
    }
});

/* 
Thêm từng node trong list 
*/
window.NodeGridItem = Backbone.View.extend({
    tagName: 'table',
    className: 'step2-node-table',
    events: {
        'click .add-use-in-node': 'addUserInNode',
        'click .add-todo-in-node': 'addTodoInNode',
        'click .delete-user-in-node': 'deleteUserInNode',
        'click .delete-todo-in-node': 'deleteTodoInNode',
        'click .delete-node': 'deleteNode',
        'change .UserInNodeMainExecutor': 'makeMainExcutor',
        'click .edit-node-1': 'edit_node',
        'change .Grid_Item_IsStart': 'changeStartingNode',
        'change .Grid_Item_IsDocNode': 'changeIsDocNode'
    },

    changeIsDocNode: function (event) {
        ///<summary>
        /// Thay đổi trạng thái của node từ nút chuyển xử lý sang loại node khác và ngược lại
        ///</summary>
        var self = this;
        var $target = $(event.currentTarget);
        if ($target) {
            self.model.save({
                'IsDocNode': $target.is(':checked') == true,
                'modified': 'IsDocNode'
            }, { sucess: function (data) {
                if (data && data.get('Status') == true) {
                    return;
                } else {
                    VH.MessageBox(jsResources.lang.RequestErrorAndRefresh, function () {
                        window.location.reload();
                    });
                }
            }
            });
        }
    },

    changeStartingNode: function (event) {
        ///<summary>
        /// Thay đổi nút bắt đầu
        ///</summary>
        var self = this;
        var $target = $(event.currentTarget);
        if ($target) {
            if ($target.is(':checked') == true) {
                self.model.save({ 'IsStart': true, 'modified': 'IsStart' }, {
                    success: function (data) {
                        if (data && data.get('Status') == true) {
                            VOFFICE.CreateFlow.onlyOneStartingNode(self.model);
                            VOFFICE.CreateFlow.hintStartingNode();
                        } else {
                            VH.MessageBox(jsResources.lang.RequestErrorAndRefresh, function () {
                                location.reload();
                            });
                        }
                    }
                });
            } else {
                self.model.save({ 'IsStart': false, 'modified': 'IsStart' }, {
                    success: function (data) {
                        if (data && data.get('Status') == true) {
                            VOFFICE.CreateFlow.hintStartingNode();
                        } else {
                            VH.MessageBox(jsResources.lang.RequestErrorAndRefresh, function () {
                                location.reload();
                            });
                        }
                    }
                });
            }
        }
    },

    edit_node: function () {
        /// <summary>
        /// Đưa node từ nodegrid lên node form để thay đổi thông tin
        ///</summary>
        var self = this;
        if (!!VOFFICE.CreateFlow) {
            VOFFICE.CreateFlow.showNodeForm(self.model);
            $('body').scrollTop(0);
        }
    },

    /*
    Biến 1 người dùng nào đó thành xử lý chính
    */
    makeMainExcutor: function (event) {
        /// <summary>
        /// Biến 1 người dùng nào đó thành xử lý chính
        /// </summary>
        event.preventDefault();
        var self = this;
        var $target = $(event.currentTarget);
        var mainExcutor = $target.is(':checked') == true;
        var userId = $target.attr('data-id');
        var nodeId = self.model.get('id');
        SaveIndicator.indicate(
            $.post('/nodeuser/update_main_executor', {
                //int nodeId, Guid userId, bool mainExcutor
                'nodeId': nodeId,
                'userId': userId,
                'mainExcutor': mainExcutor
            }, function (data) {
                if (!!data && data.Status == true) {
                    if (mainExcutor == true) {
                        var userInNode = self.model.get('UserInNode');
                        if (!!userInNode && userInNode.length > 1) {
                            var newUserInNode = [];
                            _.each(userInNode, function (item) {
                                item.Selected = item.Key == userId;
                                newUserInNode.push(item);
                            });
                            self.model.set({ 'UserInNode': newUserInNode });
                            self.model.trigger('change');
                        }
                    }
                } else {
                    VH.MessageBox(jsResources.lang.RequestErrorAndRefresh, function () {
                        location.reload();
                    });
                }

            }));
    },

    /* gọi hàm xóa node */
    deleteNode: function (event) {
        ///<summary>
        /// Xóa node trong luồng
        ///</summary>   
        var self = this;
        VH.ConfirmBox(jsResources.lang.CreateFlowNodeGridDeleteConfirm, jsResources.lang.Delete, jsResources.lang.Cancel, function () {
            SaveIndicator.indicate(
                $.post('/node/delete_node', { id: self.model.get('id') }, function (data) {
                    if (!!data && data.Status == true) {
                        location.reload();
                    } else {
                        VH.MessageBox(jsResources.lang.RequestErrorAndRefresh, function () {
                            location.reload();
                        });
                    }
                }));
        }, null);
    },

    /* xóa 1 công việc trong node */
    deleteTodoInNode: function (event) {
        ///<summary>
        /// Xóa một công việc phải làm trong node
        ///</summary>           
        var $target = $(event.currentTarget);
        var todoId = $target.attr('data-id');
        var self = this;

        if (!!todoId) {
            SaveIndicator.indicate($.post('/todo/delete_todo', { id: todoId }, function (data) {
                if (!!data && data.Status == true) {
                    var listTodo = self.model.get('TodoInNode');
                    if (listTodo.length == 1) {
                        self.model.set({ 'TodoInNode': [] });
                    } else {
                        for (var i = 0; i < listTodo.length; i++) {
                            if (listTodo[i].Key == todoId) {
                                listTodo.splice(i, 1);
                                break;
                            }
                        }
                        self.model.set({ 'TodoInNode': listTodo });
                        self.model.trigger('change');
                    }
                } else {
                    VH.MessageBox(jsResources.lang.RequestErrorAndRefresh, function () {
                        location.reload();
                    });
                }
            }));
        }
    },

    /* 
    Xóa một người dùng trong node 
    */
    deleteUserInNode: function (event) {
        ///<summary>
        /// Xóa một người dùng rả khỏi node
        ///</summary>           
        var self = this;
        var $target = $(event.currentTarget);
        var id = $target.attr('data-id');
        if (!id) return;
        SaveIndicator.indicate($.post('/nodeuser/delete_node_user', {
            'nodeId': self.model.get('id'),
            'userId': id
        }, function (data) {
            if (!!data && data.Status == true) {
                var listUser = self.model.get('UserInNode');
                if (!listUser) listUser = [];
                if (listUser.length > 0) {
                    for (var i = 0; i < listUser.length; i++) {
                        var item = listUser[i];
                        if (item.Key == id) {
                            listUser.splice(i, 1);
                            break;
                        }
                    };
                    self.model.set({ 'UserInNode': listUser });
                    self.model.trigger('change');
                }
            } else {
                VH.MessageBox(jsResources.lang.RequestErrorAndRefresh, function () {
                    location.reload();
                });
            }
        }));
    },

    /* 
    Thêm một công việc vào node 
    */
    addTodoInNode: function (event) {
        ///<summary>
        /// Hiển thị form để thêm một công việc vào node
        ///</summary>           
        var newTodo = new Todo({ 'NodeId': this.model.get('id') });
        VOFFICE.CreateFlow.showTodoForm(newTodo, this.model);
    },

    /* 
    Thêm người dùng vào node 
    */
    addUserInNode: function (event) {
        ///<summary>
        /// Hiển thị form để thêm người dùng vào một node
        ///</summary>
        var self = this;
        VH.ShowDeptTreeWithUser(function () {
            if (!!window.SelectedUsers && window.SelectedUsers.length > 0) {
                var flowId = self.model.get('FlowId');
                var id = self.model.id;
                if (!id || !flowId) return;
                _.each(window.SelectedUsers, function (item) {
                    SaveIndicator.indicate(
                        $.post('/nodeuser/add_node_user', {
                            'NodeId': id,
                            'UserId': item.UserId,
                            'FlowId': flowId,
                            'MainExecutor': false,
                            'IsActive': true
                        }, function (data) {
                            if (!!data && data.Status == true) {
                                var listUser = self.model.get('UserInNode');
                                if (!listUser) listUser = [];
                                var flag = true;
                                for (var j = 0; j < listUser.length; j++) {
                                    if (listUser[j].Key == item.UserId) {
                                        flag = false;
                                        break;
                                    }
                                }
                                if (flag) {
                                    var newItem = {
                                        'Key': item.UserId,
                                        'Value': item.UserName,
                                        'Selected': false
                                    };
                                    listUser.push(newItem);
                                }
                                self.model.set({ 'UserInNode': listUser });
                                self.model.trigger('change');
                            } else {
                                VH.MessageBox(jsResources.lang.RequestErrorAndRefresh, function () {
                                    location.reload();
                                });
                            }
                        }));
                });
                window.SelectedUsers = null;
            }
        });
    },

    initialize: function () {
        this.model.bind("change", this.render, this);
        this.model.bind("destroy", this.close, this);
    },

    render: function () {
        this.template = _.template($('#node-grid-item-template').html());
        $(this.el).html(this.template({ model: this.model.toJSON() }));
        return this;
    },

    close: function () {
        this.unbind();
        this.model.unbind("change", this.render, this);
        this.remove();
    }
});

/* 
Quản lý list các node trong phần kéo thả luồng 
*/
window.NodeRelationGrid = Backbone.View.extend({
    /* hàm tạo html */
    render: function () {
        $(this.el).html('');
        var i = 0;
        _.each(this.collection.models, function (node) {
            node.set({ 'top': 90 + i * 60 });
            node.set({ 'left': (i % 2) * 120 + 10 });
            i++;
            $(this.el).append((new NodeRelationGridItem({ model: node })).render().el);
        }, this);
        return this;
    },

    /* 
    Khi grid có thêm bản ghi thì cập nhập
    */
    initialize: function () {
        var self = this;
        this.collection.bind("reset", this.render, this);
        self.collection.bind("add", function (node) {
            //console.log(node);
            var i = self.collection.length - 1;
            //console.log(i);
            node.set({ 'top': 90 + i * 60 });
            node.set({ 'left': (i % 2) * 120 + 10 });
            $(self.el).append(new NodeRelationGridItem({ model: node }).render().el);
        });
    },

    /* Hàm hủy view */
    close: function () {
        this.unbind();
        this.collection.unbind("reset");
        this.collection.unbind("add");
        this.remove();
    }
});

/* 
Hiển thị từng nút ở phần kéo thả luồng 
*/
window.NodeRelationGridItem = Backbone.View.extend({
    initialize: function () {
        this.model.bind("change", this.silentChange, this);
        this.model.bind("destroy", this.close, this);
    },

    /* khi thông tin node thay đổi thì cập nhập lại cho các ô vuông hiển thị trong luồng 
    không viết lại hàm render vì có thể ảnh hưởng đến kết nối và jsPumb của node 
    */
    silentChange: function () {
        ///<summary>
        /// Chỉ thay đổi một phần của view khi model thay đổi
        ///</summary>           
        var $node = $('#name-' + this.model.id);
        $node.html(this.model.get('Name'));
        $node.attr('title', this.model.get('Description'));
    },

    render: function () {
        this.template = _.template($('#node-relation-item-template').html());
        $(this.el).html(this.template({ model: this.model.toJSON() }));
        return this;
    },

    close: function () {

        this.unbind();
        this.model.unbind("change", this.render, this);
        this.remove();
    }
});

/* 
Helper method to generate a color from a cycle of colors
*/
var curColourIndex = 1, maxColourIndex = 24, nextColour = function () {
    var R, G, B;
    R = parseInt(128 + Math.sin((curColourIndex * 3 + 0) * 1.3) * 128);
    G = parseInt(128 + Math.sin((curColourIndex * 3 + 1) * 1.3) * 128);
    B = parseInt(128 + Math.sin((curColourIndex * 3 + 2) * 1.3) * 128);
    curColourIndex = curColourIndex + 1;
    if (curColourIndex > maxColourIndex) curColourIndex = 1;
    return "rgb(" + R + "," + G + "," + B + ")";
};